package com.ikingtech.framework.sdk.authenticate.embedded.core.service;

import com.fasterxml.jackson.core.type.TypeReference;
import com.ikingtech.framework.sdk.authenticate.extension.IdentityExtensionLoader;
import com.ikingtech.framework.sdk.context.security.Identity;
import com.ikingtech.framework.sdk.context.security.Me;
import com.ikingtech.framework.sdk.core.response.R;
import com.ikingtech.framework.sdk.utils.Tools;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import static com.ikingtech.framework.sdk.cache.constants.CacheConstants.IDENTITY_EXTENSION_REPORTER;
import static com.ikingtech.framework.sdk.context.constant.SecurityConstants.*;

/**
 * @author tie yan
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class IdentityExtensionLoaderImpl implements IdentityExtensionLoader {

    private final StringRedisTemplate redisTemplate;

    private final LoadBalancerClient loadBalancerClient;

    @Value("${spring.application.name}")
    private String serverName;

    @Override
    public Map<String, Object> load(Identity identity) {
        Map<String, Object> result = new HashMap<>();
        //获取注册的服务名称列表
        Set<String> reporters = this.redisTemplate.opsForSet().members(IDENTITY_EXTENSION_REPORTER);
        if (null == reporters || Tools.Coll.isBlank(reporters)) {
            return result;
        }
        for (String reporter : Tools.Coll.distinct(reporters)) {
            if (reporter.equals(this.serverName)) {
                continue;
            }
            //从注册中心获取名称为reporter的服务实例ServiceInstance
            ServiceInstance client = this.loadBalancerClient.choose(reporter);
            if (null != client) {
                try {
                    //获取需要添加到Me对象的extensions属性的数据,该数据会在用户登录的时候添加,主要用于各业务方,需要就实现,返回一个Map<String,Object>
                    String loadResultStr = Tools.Http.post(Tools.Http.SCHEMA_HTTP + client.getHost() + ":" + client.getPort() + "/identity/extension/resolve",
                            Tools.Json.toJsonStr(identity),
                            Tools.Coll.newMap(
                                    Tools.Coll.Kv.of(HEADER_INNER_IDENTITY, Identity.inner()),
                                    Tools.Coll.Kv.of(HEADER_CALLER, "INNER"),
                                    Tools.Coll.Kv.of(HEADER_TENANT_CODE, Me.tenantCode())
                            ));
                    R<Map<String, Object>> loadResult = Tools.Json.toBean(loadResultStr, new TypeReference<>() {
                    });
                    if (null == loadResult) {
                        log.error("identity extension loader without result");
                    } else if (!loadResult.isSuccess()) {
                        log.error("identity extension loader fail[{}]", loadResult.getMsg());
                    } else {
                        result.putAll(loadResult.getData());
                    }
                } catch (Exception e) {
                    log.error("identity extension loader exception[{}]", e.getMessage());
                }
            }
        }
        return result;
    }
}
